fragmentace pameti

Otázka od: Ludvik Vlcek

2. 9. 2004 9:15

zdravim,

mam nasledujici problem.
V aplikaci intenzivne vyuzivam objekty typu TStringList. Tyto jsou
dynamicky vytvareny a pak zase ruseny. Kazdy tento dynamicky tvoreny
objekt "drzi" seznam stringu ruzne delky, (do cca 50 znaku az do 1500
znaku) tento seznam je od 10 do 100 stringu dlouhy.

Nejdriv jsem myslel, ze se mi nekde "vyrabim" memory leak.
(Snad)Nevyrabim. Po urcite dobe nastane, ze se aplikace zakousne a hlasi
ze neni zadna dostupma pamet. Pritom spravce procesu (w2k) hlasi, ze
volne pameti je dost. Neco podobneho (i kdyz trochu ruzne hodnoty) mi
hlasi funkce, ktere vraceji stav pameti Heapu.

Postupne jsem dosel k zaveru, ze by se mohlo jednat o docela znacnou
fragmentaci pameti, jelikoz velikost stringu ma tak velky rozptyl.

Napadlo me reseni, kdy by se jednou alokovane polozky dynamicky
nerusily, jen se "prevedly" do jakehosi poolu, ktery bych si
obhospodaroval sam. A aplikace by si z tohoto poolu "braly" potrebne
objekty a zase by sem "vracely" ty co by momentalne nepotrebovaly.

Zdalo se ze to bude fungovat docela pekne. Bohuzel ne zcela. Pad
aplikace se casove prodlouzil cca na trojnasobek, ale pak upadla ze
stejneho duvodu zase. Zjistil jsem, ze to pravdepodobne zpusobuje zpusob
prace Delphi s AnsiStringy, konkretne vlastnost ReferenCounter.
Obcas se mi stane, ze musim "prekopirovat" tento string nekam jinam.
Technicky se neprovede fyzicka kopie, ale jen se zvedne prave ten
reference counter u inkriminovaneho stringu. Kdyz pak zmenim hodnotu
stringu, teprve pak se provede alokace nove pameti a fyzicke
prekopirovani uz nove hodnoty tohoto (Samozrejme, v pripade, ze
reference counter je vetsi nez 1). Cimz mi zase "vznika" fragmentace pameti.
Nepomaha ani kdyz pri vytvoreni objektu StringListu "rovnou" taky
vytvorim jeho seznam stringu o maximalni delce a amximalnim poctu. Doba
do spadnuti se sice zase prodlouzila, ale spadlo to stejne...
 

Dal jsem zjistil, ze WideStringy tuto vlastnost nemaji, cimz by jednou
alokovana pamet pro uvedemou strukturu zustavala po dobu behu apliace
"na stale stejne miste". Nenasel jsem ale odpovidajici objekt
(TStringList), ktery by pracoval prave s timto druhem stringu.

Nenapada nekoho, jak z toho ven ??
Rad bych funkcionalitu, kerou nabizi objekt TStringList pouzival i
nadale....

diky

--
L.V.
jezevec

Odpovedá: Zbysek Hlinka

2. 9. 2004 9:24

> -----Original Message-----
> From: delphi-l-owner@clexpert.cz
> [mailto:delphi-l-owner@clexpert.cz] On Behalf Of Ludvik Vlcek
> Sent: Thursday, September 02, 2004 10:14 AM
>
> mam nasledujici problem.
> V aplikaci intenzivne vyuzivam objekty typu TStringList. Tyto
> jsou dynamicky vytvareny a pak zase ruseny. Kazdy tento
> dynamicky tvoreny objekt "drzi" seznam stringu ruzne delky,
> (do cca 50 znaku az do 1500
> znaku) tento seznam je od 10 do 100 stringu dlouhy.

Patrne sypes stringy do seznamu bez alokace velikosti seznamu. Pri tom se
deje to, ze kdyz list pretece velikost alokovaneho seznamu, zvetsi si zase o
nejaky kus vyhrazenou pamet a presune do ni stavajici seznam (sice "jen"
pointery na retezce, ale pokud se to dela casto, pak i tohle je docela zahul
pro spravu pameti, protoze ji priserne fragmentujes). Takze pokud predem
znas velikost seznamu, naalokuj si velikost listu, a pak teprve ho napln. A
samozrejme uklizej pamet, at se uvolni misto pro dalsi.

S pozdravem

Zbysek Hlinka
E-mail: hlinka zavin. hlinka.cz
Phone: +420 603 551 282



Odpovedá: Pavel Poles

2. 9. 2004 11:26

> Dal jsem zjistil, ze WideStringy tuto vlastnost nemaji, cimz by jednou
> alokovana pamet pro uvedemou strukturu zustavala po dobu behu apliace
> "na stale stejne miste". Nenasel jsem ale odpovidajici objekt
> (TStringList), ktery by pracoval prave s timto druhem stringu.

v JCL je TWideStrings a TWideStringList, pouzivam k naproste spokojenosti...

Pavel Poles


Odpovedá: Petr Vones

2. 9. 2004 12:03

From: "Ludvik Vlcek" <l.vlcek@noel-plus.cz>
> Nejdriv jsem myslel, ze se mi nekde "vyrabim" memory leak.
> (Snad)Nevyrabim. Po urcite dobe nastane, ze se aplikace zakousne a hlasi
> ze neni zadna dostupma pamet. Pritom spravce procesu (w2k) hlasi, ze
> volne pameti je dost. Neco podobneho (i kdyz trochu ruzne hodnoty) mi
> hlasi funkce, ktere vraceji stav pameti Heapu.
>
> Postupne jsem dosel k zaveru, ze by se mohlo jednat o docela znacnou
> fragmentaci pameti, jelikoz velikost stringu ma tak velky rozptyl.

Tohle je teoreticky mozne, ale nejdrive bych pro jistotu zkontroloval ten
leak. Prece jen je to trochu podezrele.

> Napadlo me reseni, kdy by se jednou alokovane polozky dynamicky
> nerusily, jen se "prevedly" do jakehosi poolu, ktery bych si
> obhospodaroval sam. A aplikace by si z tohoto poolu "braly" potrebne
> objekty a zase by sem "vracely" ty co by momentalne nepotrebovaly.

Moznosti je nekolik:

- napsat vlastni TStringList ktery bude alokovat pamet z privatniho heapu.
  Delphi memory manager ovsem neumoznuje mit v aplikaci vice jeho instanci,
  takze by si musel pouzit heap manager z Windows, ktery neni nejrychlejsi
- napsat vlastni TStringList ktery bude mit "predvidatelny" pocet polozek a
  tem pak implementujes metody NewInstance a FreeInstance tak, aby si brali
  pamet z nejakeho linearniho poolu.
- zmenit logiku aplikace tak, aby toto vubec nevznikalo

> Dal jsem zjistil, ze WideStringy tuto vlastnost nemaji, cimz by jednou
> alokovana pamet pro uvedemou strukturu zustavala po dobu behu apliace
> "na stale stejne miste". Nenasel jsem ale odpovidajici objekt
> (TStringList), ktery by pracoval prave s timto druhem stringu.

WideString je kvuli kompatibilite s COMem (BSTR) implementovan tak, ze pouziva
memory manager z Windows. Takze tam problem bud nevznika nebo ano, ale ty jej
akorat nejsi schopen (vcas) detekovat.

> Nenapada nekoho, jak z toho ven ??
> Rad bych funkcionalitu, kerou nabizi objekt TStringList pouzival i
> nadale....

Popis vice co s tim vlastne delas.

Petr Vones


Odpovedá: Lukas Gebauer

2. 9. 2004 12:56

> V aplikaci intenzivne vyuzivam objekty typu TStringList. Tyto jsou
> dynamicky vytvareny a pak zase ruseny. Kazdy tento dynamicky tvoreny

Zkus jednoduchy experiment, a podivej se na tenhle clanecek z WIKI
Synapse:

http://synapse.ararat.cz/wiki/index.php?page=Article004


--
Lukas Gebauer.

E-mail: gebauerl@mlp.cz
http://www.ararat.cz/synapse/ - Ararat Synapse - TCP/IP Lib.


Odpovedá: Ludvik Vlcek

2. 9. 2004 15:29

Lukas Gebauer napsal(a):
>>V aplikaci intenzivne vyuzivam objekty typu TStringList. Tyto jsou
>>dynamicky vytvareny a pak zase ruseny. Kazdy tento dynamicky tvoreny
>
>
> Zkus jednoduchy experiment, a podivej se na tenhle clanecek z WIKI
> Synapse:
>
> http://synapse.ararat.cz/wiki/index.php?page=Article004
>
>
OK,
vyzkousim, dam vedet ...